//-----------------------------------------------------------------------
// <copyright file="UpdateSslFlags.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Shaun Wilde (ICS)</author>
// <email>v-swilde</email>
// <date>2006-04-25</date>
// <summary>TODO</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.Web.WebSite
{
    using System;
    using Microsoft.Sdc.Tasks.Configuration.Web;

    /// <summary>
    /// Update the SslFlags for a web site or a virtual directory
    /// </summary>
    public class UpdateSslFlags : TaskBase
    {
        /// <summary>
        /// the ssl flags
        /// </summary>
        private string sslAccessFlags;

        /// <summary>
        /// The description of the web site to locate
        /// </summary>
        private string description;

        /// <summary>
        /// The identifier of the website to locate
        /// </summary>
        private string identifier;

        /// <summary>
        /// a named vdir should the mapping be required on a subfolder
        /// </summary>
        private string virtualDirectory;
        private string machineName = "localhost";

        /// <summary>
        /// Gets or sets the name of the machine to operate on. Default is localhost
        /// </summary>
        public string MachineName
        {
            get { return this.machineName; }
            set { this.machineName = value; }
        }

        /// <summary>
        /// a named vdir should the mapping be required on a subfolder
        /// </summary>
        public string VirtualDirectory
        {
            get { return this.virtualDirectory; }
            set { this.virtualDirectory = value; }
        }

        /// <summary>
        /// Description of web site to modify
        /// </summary>
        /// <value>A valid web site description</value>
        /// <remarks>If this parameter is not specified you must specify the site <seealso cref="Identifier">Identifier</seealso> 
        /// for the site you wish to start</remarks>
        public string Description
        {
            get { return (this.description ?? String.Empty); }

            set { this.description = value; }
        }

        /// <summary>
        /// web site idenfitier to modify
        /// </summary>
        /// <value>A valid web site identifier</value>
        /// <remarks>If this parameter is not specified you must specify the site <seealso cref="Description">Description</seealso> 
        /// for the site you wish to start</remarks>
        public string Identifier
        {
            get { return (this.identifier ?? String.Empty); }

            set { this.identifier = value; }
        }

        /// <summary>
        /// SslAccessFlags. Configures the ssl restrictions for the site that is to be updated.
        /// </summary>
        /// <value>integer</value>
        /// <remarks>
        /// 
        /// The following values are valid. Use a space separated list to combine flags.
        /// Or simply supply the integer value required.
        /// 
        /// Defaults to SslAny (SSL not required)
        /// 
        ///  SslAny = 0x00000000
        ///  RequireSsl = 0x00000008
        ///  RequireSsl128 = 0x00000100
        ///  MapClientCert = 0x00000080
        ///  RequestClientCert = 0x00000020
        ///  RequireClientCert = 0x00000040
        ///  
        /// </remarks>
        public string SslAccessFlags
        {
            get { return (this.sslAccessFlags ?? String.Empty); }

            set { this.sslAccessFlags = value; }
        }

        /// <summary>
        /// Update the ssl flags
        /// </summary>
        protected override void InternalExecute()
        {
            if (this.description == null && this.identifier == null)
            {
                throw new TaskException("Web.DescriptionOrIdentifier");
            }

            if (this.description != null && this.identifier != null)
            {
                throw new TaskException("Web.DescriptionOrIdentifierNotBoth", this.description, this.identifier);
            }

            int id = Utilities.CheckWebSiteDescriptionOrIdentifier(this.description, this.identifier, "Update Ssl Flags", this.MachineName);
            if (Microsoft.Sdc.Tasks.Configuration.Web.WebSite.Exists(this.MachineName, id))
            {
                Microsoft.Sdc.Tasks.Configuration.Web.WebSite site = Microsoft.Sdc.Tasks.Configuration.Web.WebSite.Load(this.MachineName, id);

                if (this.VirtualDirectory == null)
                {
                    System.DirectoryServices.DirectoryEntry de = site.Root.DirectoryEntry;
                    System.DirectoryServices.PropertyValueCollection sslFlags = de.Properties["AccessSSLFlags"];
                    sslFlags.Clear();
                    sslFlags.Add(ParseSslFlags(this.SslAccessFlags));
                    de.CommitChanges();
                }
                else
                {
                    System.DirectoryServices.DirectoryEntry de = site.Root.DirectoryEntry;
                    System.DirectoryServices.DirectoryEntry de2 = de.Children.Find(this.VirtualDirectory, "IIsWebVirtualDir");
                    System.DirectoryServices.PropertyValueCollection sslFlags = de2.Properties["AccessSSLFlags"];
                    sslFlags.Clear();
                    sslFlags.Add(ParseSslFlags(this.SslAccessFlags));
                    de2.CommitChanges();
                }
            }
        }

        /// <summary>
        /// Extract the ssl flags from the supplied string
        /// </summary>
        /// <param name="flagString">the string contains space delimited ssl flags</param>
        /// <returns>The ssl flags</returns>
        private static ServerCertificate.SslAccessFlags ParseSslFlags(string flagString)
        {
            int sslFlags;

            // we allow flags to be specified as an int or as a space separated list of named flags
            if (!int.TryParse(flagString, out sslFlags))
            {
                string[] flagStringSplit = flagString.Split(' ');
                foreach (string splitItem in flagStringSplit)
                {
                    int flag = (int) Enum.Parse(typeof(ServerCertificate.SslAccessFlags), splitItem, true);
                    sslFlags = sslFlags | flag;
                }
            }

            return (ServerCertificate.SslAccessFlags) sslFlags;
        }
    }
}